﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Workflow.Activities.Rules;
using System.Diagnostics;

namespace RelationExpertSystem.Models
{
    public class RelationModel
    {
        private ISession _session;
        private IRulesManager _rulesManager;
        private bool _newRelationsFound = false;

        public event EventHandler<FactsEventArgs> FactsUpdated
        {
            add { _session.FactsUpdated += value; }
            remove { _session.FactsUpdated -= value; }
        }

        public event EventHandler<FactsEventArgs> NewFactsLoaded;
        private void RaiseNewFactsLoaded(FactsEventArgs args)
        {
            EventHandler<FactsEventArgs> eh = NewFactsLoaded;
            if (eh != null)
                eh(this, args);
        }

        public event EventHandler<MessageEventArgs> NewInference
        {
            add { _session.NewInference += value; }
            remove { _session.NewInference -= value; }
        }

        public event EventHandler RulesUpdated;
        protected void RaiseRulesUpdated(EventArgs args)
        {
            EventHandler eh = RulesUpdated;
            if (eh != null)
                eh(this, args);
        }

        public RelationModel(IRulesManager rulesManager, ISession session)
        {
            _rulesManager = rulesManager;
            _session = session;
            _session.FactsLoaded += new EventHandler<FactsEventArgs>(HandleSession_FactsLoaded);
            _newRelationsFound = false;
        }

        public void NewRules(string name, string description)
        {
            _rulesManager.NewRules(name, description);
        }

        public void LoadRules()
        {
            _rulesManager.LoadRules();
            RaiseRulesUpdated(EventArgs.Empty);
        }

        public void EditRules()
        {
            _rulesManager.EditRules();
            RaiseRulesUpdated(EventArgs.Empty);
        }

        public IEnumerable<Rule> GetRules()
        {
            return _rulesManager.GetRules();
        }

        public void NewSession(ISession session)
        {
            _session.FactsLoaded -= new EventHandler<FactsEventArgs>(HandleSession_FactsLoaded);
            _session = session;
            _session.FactsLoaded += new EventHandler<FactsEventArgs>(HandleSession_FactsLoaded);
        }

        public void LoadFacts()
        {
            _session.LoadFacts();
        }

        public void EditFacts()
        {
            _session.EditFacts();
        }

        public void NewFacts()
        {
            _session.NewFacts();
        }

        public void Infer()
        {
            _session.NewInference += new EventHandler<MessageEventArgs>(HandleSession_NewInference);
            DateTime start = DateTime.Now;
            TimeSpan span;
            do
            {
                DateTime loopStart = DateTime.Now;
                _newRelationsFound = false;
                _session.Infer();
                span = DateTime.Now - loopStart;
                Debug.WriteLine(String.Format("Loop took {0} seconds", span.TotalSeconds.ToString()));
            } while (_newRelationsFound);
            span = DateTime.Now - start;
            Debug.WriteLine(String.Format("Inference took {0} seconds", span.TotalSeconds.ToString()));
            _session.NewInference -= new EventHandler<MessageEventArgs>(HandleSession_NewInference);
        }

        private void HandleSession_NewInference(object sender, MessageEventArgs args)
        {
            _newRelationsFound = true;
        }

        private void HandleSession_FactsLoaded(object sender, FactsEventArgs args)
        {
            RaiseNewFactsLoaded(args);
        }
    }
}
